﻿using Newtonsoft.Json;
using System.Net;
using System.Text;

namespace App.Tools.Https
{
    /// <summary>
    /// api http请求帮助类
    /// </summary>
    public class Http
    {
        static Http() { }
        private Http()
        {
        }

        private static readonly HttpClient _instance = new HttpClient();

        /// <summary>
        /// 
        /// </summary>
        public static HttpClient getInstance
        {
            get
            {
                return _instance;
            }
        }
    }

    /// <summary>
    /// http 帮组类
    /// </summary>
    public static class HttpClientHelp
    {

        #region get

        /// <summary>
        /// 有参get
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="paramItems"></param>
        /// <returns></returns>
        public static async Task<string> Get(string url, Dictionary<string, string> paramItems)
        {
            var httpResult = await GetMethod(url, paramItems);
            return await GetResult(httpResult, url);
        }

        /// <summary>
        /// 无参get
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<T> Get<T>(string url)
        {
            return await Get<T>(url, null);
        }

        /// <summary>
        /// 有参get
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="paramItems"></param>
        /// <returns></returns>
        public static async Task<T> Get<T>(string url, Dictionary<string, string> paramItems)
        {
            var httpResult = await GetMethod(url, paramItems);
            return await GetResult<T>(httpResult, url);
        }

        #endregion

        #region post

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public static async Task PostAsync<T>(string url, T postData = default(T))
        {
            await PostAsync<T, string>(url, postData);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T1"></typeparam>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public static async Task<T1> PostAsync<T, T1>(string url, T postData = default(T))
        {
            return await PostAsync<T, T1>(url, postData);
        }

        /// <summary>
        /// post
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static async Task<T1> PostAsync<T, T1>(string url, T postData = default(T),
            string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            var httpResult = await PostMethod<T>(url, postData, contentType, headers);
            return await GetResult<T1>(httpResult, url);
        }

        public static async Task<string> PostAsync<T>(string url, T postData = default(T),
        string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            var httpResult = await PostMethod<T>(url, postData, contentType, headers);
            return await GetResult(httpResult, url);
        }

        #endregion

        #region 核心方法


        /// <summary>
        /// get 核心方法
        /// </summary>
        /// <param name="url"></param>
        /// <param name="paramItems"></param>
        /// <returns></returns>
        private static async Task<HttpResponseMessage> GetMethod(string url, Dictionary<string, string> paramItems)
        {
            var paramStr = new StringBuilder();

            if (paramItems != null && paramItems.Count != 0)
            {
                for (int i = 0; i < paramItems.Count; i++)
                {
                    var kv = paramItems.ElementAt(i);
                    if (i == 0)
                    {
                        paramStr.Append(string.Format("{0}={1}", kv.Key, kv.Value));
                    }
                    else
                    {
                        paramStr.Append(string.Format("&{0}={1}", kv.Key, kv.Value));
                    }
                }
            }

            url = string.Format("{0}?{1}", url, paramStr.ToString());

            var response = await Http.getInstance.GetAsync(url);
            return response;
        }

        /// <summary>
        /// post 核心方法
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="contentType"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        private static async Task<HttpResponseMessage> PostMethod<T>(string url, T postData = default(T),
            string contentType = "application/json", Dictionary<string, string> headers = null)
        {
            if (headers != null)
            {
                foreach (var header in headers)
                {
                    Http.getInstance.DefaultRequestHeaders.Add(header.Key, header.Value);
                }
            }

            var postStr = string.Empty;
            if (postData != null)
            {
                postStr = JsonConvert.SerializeObject(postData);
            }

            using (HttpContent httpContent = new StringContent(postStr, Encoding.UTF8))
            {
                if (contentType != null)
                {
                    httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
                }

                var response = await Http.getInstance.PostAsync(url, httpContent);
                return response;
            }
        }

        private static async Task<string> GetResult(HttpResponseMessage response, string url)
        {
            if (response.StatusCode == HttpStatusCode.OK)
            {
                var contenType = response.Content.Headers.ContentType.MediaType;
                var resultJson = await response.Content.ReadAsStringAsync();
                return resultJson;
            }
            else if (response.StatusCode == HttpStatusCode.InternalServerError)
            {
                throw new Exception(string.Format("请求url={0},未找到相关接口", url));
            }
            else if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                throw new Exception(string.Format("请求url={0},未认证401", url));
            }
            else
            {
                throw new Exception("请求异常");
            }
        }

        private static async Task<T> GetResult<T>(HttpResponseMessage response, string url)
        {
            var contenType = response.Content.Headers.ContentType.MediaType;
            if (contenType == "application/json" || contenType.Contains("json"))
            {
                var resultJson = await GetResult(response, url);
                if (string.IsNullOrWhiteSpace(resultJson))
                {
                    return default(T);
                }

                return JsonConvert.DeserializeObject<T>(resultJson);
            }
            else
            {
                return default(T);
            }
        }

        #endregion

    }
}